package chat.demo.server.handler;

import chat.demo.model.ChatHis;
import chat.demo.model.Message;
import chat.util.FileOperation;
import chat.util.SpringUtil;
import com.alibaba.fastjson.JSON;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;


@Slf4j
public class MyServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    private final String TEMP_FILE = "TEMP_FILE_NAME";
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext,
                                TextWebSocketFrame textWebSocketFrame) throws Exception {
        System.out.println("in channelRead0");
        String text = textWebSocketFrame.text();
        System.out.println(JSON.parseObject(textWebSocketFrame.text()));
        System.out.println("Get the message: " +  text);
        ChatHis chatHis = JSON.parseObject(text, ChatHis.class);
        String message_file_path = FileOperation.buildFileName(TEMP_FILE);
        FileOperation.storeMessage(message_file_path, chatHis.getMsg(), chatHis.getUserId());
        try {
            System.out.println(chatHis);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        // send message to all clients
        for (Channel client :  clients) {
            client.writeAndFlush(new TextWebSocketFrame(
                    JSON.toJSONString(chatHis)));
        }
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                System.out.println("read free time limit triggered");
            } else if (idleStateEvent.state() == IdleState.WRITER_IDLE) {
                System.out.println("write free time limit triggered");
            } else if (idleStateEvent.state() == IdleState.ALL_IDLE) {
                System.out.println("====================");
                System.out.println("Both read and write time limit triggered");
                System.out.println("close the channel");
                System.out.println("====================");
                ctx.channel().close();
                clients.remove(ctx.channel());
            }
        } else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            Message message = new Message();
            String message_file_path = FileOperation.buildFileName(TEMP_FILE);
            FileOperation.storeMessage(message_file_path, "new user join the chatroom");
            List<ChatHis> chatHisList = FileOperation.readHisMessage(message_file_path, null);
            message.setChat(chatHisList);
            message.setUserId(ctx.channel().id().toString());
            try {
                clients.add(ctx.channel());
                message.setUsers(clients.size());
                for (Channel client : clients) {
                    System.out.println("sending init message......");
                    System.out.println(message);
                    client.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
                }
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("Close the channel");
        log.info(cause.getMessage());
        ctx.channel().close();
        clients.remove(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("============remove======" + ctx.channel().id());
        clients.remove(ctx.channel());
        System.out.println(clients.size());
    }

}
